/*  PCSX2 - PS2 Emulator for PCs
 *  Copyright (C) 2002-2010  PCSX2 Dev Team
 *
 *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU Lesser General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with PCSX2.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "AppCommon.h"
#include "Elfheader.h"

#include <wx/dnd.h>
#include <wx/listctrl.h>

struct SaveConfig
{
public:
	bool eeBranchHack;
	bool fastCDVD;
	bool IntcStat;
	bool vuBlockHack;
	bool vuFlagHack;
	bool vuMinMax;
	bool WaitLoop;

	bool EETimingHack;
	bool FpuCompareHack;
	bool FpuMulHack;
	bool FpuNegDivHack;
	bool IPUWaitHack;
	bool OPHFlagHack;
	bool SkipMPEGHack;
	bool VuAddSubHack;
	bool VuClipFlagHack;
	bool XgKickHack;
};
//SaveConfig SaveConfigure;

// --------------------------------------------------------------------------------------
//  ConfigGame
// --------------------------------------------------------------------------------------
class ConfigGame
{
	Pcsx2Config dest;
	wxString m_Serial;
	u32 m_CRC;

public:
	ConfigGame();
	ConfigGame(wxString Serial, u32 CRC);

	Pcsx2Config LoadConf(const u32& CRC = ElfCRC, const wxString& Serial = DiscSerial, const Pcsx2Config& _dest = g_Conf->EmuOptions);
	void SaveConf(const Pcsx2Config& _dest, const u32& CRC = ElfCRC, const wxString& Serial = DiscSerial);
	wxString GetIniFolder(bool create = false);
	wxString GetGameId();
	void Conf(IniInterface& ini);
	void ConfigurePlugin(const PluginsEnum_t& pid);
	void ConfigGame::ConvertPluginFilenames( wxString (&passins), const PluginsEnum_t& pid );

	uint		SetConf(IniInterface& ini, const wxString& var, uint		reg);
	bool		SetConf(IniInterface& ini, const wxString& var, bool		reg);
	wxString	SetConf(IniInterface& ini, const wxString& var, wxString	reg);
	u8			SetConf(IniInterface& ini, const wxString& var, u8			reg);
};

class ConfigGameDialog 
	: public wxDialogWithHelpers
	, public ConfigGame
{
protected:
	u32 m_CRC;
	wxString m_Serial;

	Pcsx2Config dest;

	wxSlider*		m_slider_eecycle;
	wxSlider*		m_slider_vustealer;
	wxSlider*		m_slider_iopstealer;

	pxRadioPanel*	m_panel_VU0;
	pxRadioPanel*	m_panel_VU1;

	pxRadioPanel*	m_VU_RoundModePanel;
	pxRadioPanel*	m_VU_ClampModePanel;

	pxRadioPanel*	m_FPU_RoundModePanel;
	pxRadioPanel*	m_FPU_ClampModePanel;

	pxCheckBox*		m_VU_FTZ;
	pxCheckBox*		m_VU_DAZ;
	pxCheckBox*		m_FPU_FTZ;
	pxCheckBox*		m_FPU_DAZ;

	pxCheckBox*	eeBranchHack;
	pxCheckBox*	fastCDVD;
	pxCheckBox*	IntcStat;
	pxCheckBox*	vuBlockHack;
	pxCheckBox*	vuFlagHack;
	pxCheckBox*	vuMinMax;
	pxCheckBox*	WaitLoop;

	pxCheckBox*	EETimingHack;
	pxCheckBox*	FpuCompareHack;
	pxCheckBox*	FpuMulHack;
	pxCheckBox*	FpuNegDivHack;
	pxCheckBox*	IPUWaitHack;
	pxCheckBox*	OPHFlagHack;
	pxCheckBox*	SkipMPEGHack;
	pxCheckBox*	VuAddSubHack;
	pxCheckBox*	VuClipFlagHack;
	pxCheckBox*	XgKickHack;
public:
	virtual ~ConfigGameDialog()  throw() {}
	ConfigGameDialog( wxWindow* parent, const u32& CRC = ElfCRC, const wxString& Serial = DiscSerial );

protected:
	void OnOk_Click			( wxCommandEvent& event );
	void Slider_Click		( wxScrollEvent&  event );

	void ConfigGSPlugin		( wxCommandEvent& event );
	void ConfigSPU2Plugin	( wxCommandEvent& event );
	void ConfigCDVDPlugin	( wxCommandEvent& event );
	void ConfigPADPlugin	( wxCommandEvent& event );
	void ConfigFWPlugin		( wxCommandEvent& event );
	void ConfigUSBPlugin	( wxCommandEvent& event );
	void ConfigDEV9Plugin	( wxCommandEvent& event );

	void LoadConfig();
};


// --------------------------------------------------------------------------------------
//  GameListItem
// --------------------------------------------------------------------------------------

enum GameColumns
{
	GameCol_Filename,
	GameCol_Size,
	GameCol_TypeDisk,
	GameCol_TypeGame,
	GameCol_CRC,
	GameCol_Serial,
	GameCol_Region,
	GameCol_IsoFormat,

	GameCol_DateModified,
	GameCol_DateCreated,
	//GameCol_Image,

	GameCol_Count
};

struct GameListViewColumnInfo
{
	const wxChar*		name;
	int					width;
	wxListColumnFormat	align;
};

struct GameListItem
{
	float		gameFileSizeMB;

	wxFileName  Game;
	wxDateTime	DateCreated;
	wxDateTime	DateModified;
	wxString    GameName;
	wxString    DiskName;
	wxString    Serial;
	wxString    showtype;
	wxString    showdisctype;
	wxString    gamesize;
	wxString    Region;
	wxString    s[GameCol_Count];
	bool        TCompressed;
	bool        UtCompressed;
	bool        BlockDump;
	bool        CAborted;
	u32         crc;
	//uint			Count;

	GameListItem()
	{
		//Count			= 0;
		crc				= 0;
		gameFileSizeMB	= 0;
		DateCreated		= 0;
		DateModified	= 0;

		showdisctype	= L"Unknown";
		showtype		= L"Illegal Disk";
		gamesize		= L"MB";
		Serial			= L"Unknown";

		Game			= wxEmptyString;
		GameName		= wxEmptyString;
		DiskName		= wxEmptyString;
		Region			= wxEmptyString;

		TCompressed    = false;
		UtCompressed   = false;
		BlockDump      = false;
		CAborted       = false;
	}

	//bool operator==( const GameListItem& right ) const;
	//bool operator!=( const GameListItem& right ) const;
};

typedef std::vector<GameListItem> GameList;

class IGameList
{
public:
	virtual void RefreshList()                                   const=0;
	virtual int GetLength()                                      const=0;
	
	virtual const GameListItem&   GetGame     ( int idx )        const=0;
	virtual       GameListItem&   GetGame     ( int idx )             =0;
	virtual       void UpdateItemCol ( GameListItem& it )             =0;
	virtual wxDirName             GetGamePath()                  const=0;
};

class GameSelectorViewPanel : public wxListView
{
	typedef wxListView _parent;

protected:
	const IGameList*		m_GameProvider;

	// specifies the target of a drag&drop operation
	int					m_TargetedItem;

public:
	virtual ~GameSelectorViewPanel() throw() { }
	GameSelectorViewPanel( wxWindow* parent )
		: _parent( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_VIRTUAL )
	{
		m_GameProvider = NULL;
	}

	virtual void SetGameCount( int length )=0;
	virtual void LoadSaveColumns( IniInterface& ini )=0;
	virtual const GameListViewColumnInfo& GetDefaultColumnInfo( uint idx ) const=0;

	virtual void SetGameProvider( IGameList* face )
	{
		m_GameProvider = face;
		SetGameCount( m_GameProvider ? m_GameProvider->GetLength() : 0 );
	}
	
	virtual const IGameList& GetGameProvider() const
	{
		pxAssume( m_GameProvider );
		return *m_GameProvider;
	}
	
	virtual void SetTargetedItem( int sel )
	{
		if( m_TargetedItem == sel ) return;

		if( m_TargetedItem >= 0 ) RefreshItem( m_TargetedItem );
		m_TargetedItem = sel;
		RefreshItem( sel );
	}
};

class GameSelectorPanel_List : public GameSelectorViewPanel
{
	typedef GameSelectorViewPanel _parent;

public:
	virtual ~GameSelectorPanel_List() throw() { }
	GameSelectorPanel_List( wxWindow* parent );

	void CreateColumns();
	virtual void LoadSaveColumns( IniInterface& ini );
	virtual const GameListViewColumnInfo& GetDefaultColumnInfo( uint idx ) const;
	virtual void SetGameCount( int length );

protected:
	// Overrides for wxLC_VIRTUAL
	virtual wxString OnGetItemText(long item, long column) const;
	virtual int OnGetItemImage(long item) const;
	virtual int OnGetItemColumnImage(long item, long column) const;
	virtual wxListItemAttr *OnGetItemAttr(long item) const;
};
